package pers.cz.orm.dao;

import pers.cz.common.connect.ConnectionFactory;
import pers.cz.common.connect.StoreType;
import pers.cz.common.connect.IConnection;
import pers.cz.common.pub.AbstractEntity;
import pers.cz.common.meta.MetaHolder;
import pers.cz.common.meta.TableMeta;
import pers.cz.common.pub.CommonDao;
import pers.cz.common.sharding.DefaultShardingStrategy;
import pers.cz.common.sharding.IShardingStrategy;
import pers.cz.orm.dao.support.DbOperatorListener;
import pers.cz.orm.dao.support.DefaultDbOperatorListener;
import pers.cz.orm.db.DataSourceFactory;

import java.util.List;
import java.util.Map;

/**
 * @program: jef-orm
 * @description: 抽象dao
 * @author: Cheng Zhi
 * @create: 2023-08-10 10:10
 **/
public abstract class AbstractDbDao<T> implements CommonDao {

   private IConnection connection;

   /**
    * sql执行引擎
    */
   public SqlEngine sqlEngine;

   public static DbOperatorListener dbOperatorListener;

   public static ConnectionFactory connectionFactory;

   public static IShardingStrategy shardingStrategy;

   static {
      // 初始化连接池
      connectionFactory = new DataSourceFactory();
      // sqlEngine = new ReuseSqlEngine(connection); // 可复用statement的执行引擎
      dbOperatorListener = new DefaultDbOperatorListener();

      shardingStrategy = new DefaultShardingStrategy();
   }

   private void initEngine() {
      connection = connectionFactory.getConnection(StoreType.SIMPLEDB);
      // todo 通过jefConfig来动态指定执行引擎
      sqlEngine = new DefaultSqlEngine(connection);
   }

   public T load(AbstractEntity abstractEntity) {
      initEngine();
      T result = load0(abstractEntity);
      close();
      return result;
   }

   public List<T> find(AbstractEntity abstractEntity) {
      initEngine();
      List<T> result = find0(abstractEntity);
      close();
      return result;
   }

   public int insert(AbstractEntity abstractEntity) {
      initEngine();
      int count = insert0(abstractEntity);
      close();
      return count;
   }

   @Override
   public int override(AbstractEntity abstractEntity) {
      initEngine();
      int count = override0(abstractEntity);
      close();
      return count;
   }

   public int update(AbstractEntity abstractEntity) {
      initEngine();
      int count = update0(abstractEntity);
      close();
      return count;
   }

   public int delete(AbstractEntity abstractEntity) {
      initEngine();
      int count = delete0(abstractEntity);
      close();
      return count;
   }

   public int batchInsert(List abstractEntitys) {
      initEngine();
      int count = batchInsert0(abstractEntitys);
      close();
      return count;
   }

   public List selectAs(String sql, Class resultType, Map map) {
      initEngine();
      List result = selectAs0(sql, resultType, map);
      close();
      return result;
   }

   protected abstract T load0(AbstractEntity abstractEntity);

   protected abstract List<T> find0(AbstractEntity abstractEntity);

   protected abstract int insert0(AbstractEntity abstractEntity);

   protected abstract int override0(AbstractEntity abstractEntity);

   protected abstract int update0(AbstractEntity abstractEntity);

   protected abstract int delete0(AbstractEntity abstractEntity);

   protected abstract int batchInsert0(List abstractEntitys);

   protected abstract List selectAs0(String sql, Class resultType, Map map);

   public TableMeta initTableMeta(AbstractEntity entity) {
       return MetaHolder.initTable(entity);
   }

   public DbOperatorListener getDbListener() {
      return dbOperatorListener;
   }

   public void close() {
      if (sqlEngine != null) {
         sqlEngine.close();
      }
   }

   @Override
   protected void finalize() throws Throwable {
      close();
   }
}
